package org.sction.util;

import java.io.File;
import java.io.IOException;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class WebXML {
	private static String basepath;
	private String path = "";
	private String encoding = "";
	private Document document = null;

	public static String getBasepath() {
		return basepath;
	}

	public static void setBasepath(String basepath) {
		WebXML.basepath = basepath;
	}

	public static WebXML newInstance() throws ParserConfigurationException,
			SAXException, IOException {
		WebXML wx = new WebXML("/WEB-INF/web.xml");
		return wx;
	}

	public WebXML(String path) throws ParserConfigurationException,
			SAXException, IOException {
		this.path = (basepath == null ? path : basepath + path);
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		document = builder.parse(new File(path));
		document.normalize();
	}

	/**
	 * 写文档到web.xml文件
	 * 
	 * @return
	 */
	public boolean write() {
		boolean flag = true;
		try {
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();
			if (encoding != null && !encoding.trim().equals("")) {
				transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
			}
			DOMSource source = new DOMSource(document);
			StreamResult result = new StreamResult(new File(path));
			transformer.transform(source, result);
		} catch (Exception ex) {
			flag = false;
		}
		return flag;
	}

	/**
	 * 使用xpath查询节点
	 * 
	 * @param expr
	 * @param qname
	 *            XPathConstants.NODE
	 * @return
	 * @throws XPathExpressionException
	 */
	public Object xpathValue(String expr, QName qname)
			throws XPathExpressionException {
		XPathFactory factory = XPathFactory.newInstance();
		XPath xpath = factory.newXPath();
		XPathExpression xpathExpr = xpath.compile("/web-app" + expr);
		return xpathExpr.evaluate(document, qname);
	}

	public String getContextParam(String name) throws XPathExpressionException {
		Node paramValue = (Node) xpathValue("/context-param[param-name=\""
				+ name + "\"]/param-value", XPathConstants.NODE);

		if (paramValue != null) {
			return paramValue.getTextContent();
		}
		return null;
	}

	public boolean updateContextParam(String name, String value)
			throws XPathExpressionException {
		Node paramValue = (Node) xpathValue("/context-param[param-name=\""
				+ name + "\"]/param-value", XPathConstants.NODE);
		if (paramValue == null) {
			Element contextElement = document.createElement("context-param");
			Element nameElement = document.createElement("param-name");
			nameElement.setTextContent(name.trim());
			Element valueElement = document.createElement("param-value");
			valueElement.setTextContent(value.trim());
			contextElement.appendChild(nameElement);
			contextElement.appendChild(valueElement);
			Node root = document.getDocumentElement();
			root.appendChild(contextElement);
			return write();
		} else {
			if (value != null
					&& !value.trim().equals(paramValue.getTextContent())) {
				paramValue.setTextContent(value.trim());
				return write();
			}
		}
		return true;
	}

	public boolean addWelcomeFileList(String page)
			throws XPathExpressionException {
		boolean existWFL = false;
		Node wflNode = (Node) xpathValue("/welcome-file-list",
				XPathConstants.NODE);
		Node pageNode = null;
		if (wflNode != null) {
			existWFL = true;
			pageNode = (Node) xpathValue("/welcome-file-list[welcome-file=\""
					+ page + "\"]", XPathConstants.NODE);
		} else {
			wflNode = document.createElement("welcome-file-list");
		}
		if (pageNode == null) {
			Element pageElement = document.createElement("welcome-file");
			pageElement.setTextContent(page.trim());
			wflNode.appendChild(pageElement);
			if (!existWFL) {
				Node root = document.getDocumentElement();
				root.appendChild(wflNode);
			}
			return write();
		}
		return true;
	}

	public boolean removeWelcomeFileList(String page)
			throws XPathExpressionException {
		Node pageNode = (Node) xpathValue("/welcome-file-list[welcome-file=\""
				+ page + "\"]", XPathConstants.NODE);
		if (pageNode != null) {
			pageNode.getParentNode().removeChild(pageNode);
			return write();
		}
		return true;
	}

	public static void main(String[] args) throws ParserConfigurationException,
			SAXException, IOException, XPathExpressionException {
		WebXML wx = new WebXML("web.xml");
		wx.updateContextParam("ScanningPat1h", "342231");
		wx.removeWelcomeFileList("test1.jsp");
		wx.addWelcomeFileList("index.jsp");
		wx.getContextParam("ScanningPat1h");
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

}
